#ifndef _ASTAR_TYPES_H_
#define _ASTAR_TYPES_H_
#include <vector>
#include <math.h>
#include <iostream>

// States for each cell on the Map.
const int WALL              = 0;
const int OPEN              = 1;
const int TOWER_BASE        = 2;
const int TOWER_BASE_OPEN   = 3;
const int TOWER_BASE_CLOSED = 4;
const int POWER_CORE        = 5;
const int CORNER            = 100;
const int PATH_NODE         = 101;

// NodeIndex represents an (x, y) index on the grid.
struct NodeIndex
{
  NodeIndex(void) : x(0), y(0) {}
  NodeIndex(int X, int Y) : x(X), y(Y) {}
  NodeIndex(const NodeIndex& rhs) : x(rhs.x), y(rhs.y) {}
  
  // operators
  bool operator < (const NodeIndex& rhs) const {return (x == rhs.x ? (y < rhs.y) : x < rhs.x);}
  NodeIndex& operator = (const NodeIndex& rhs) {x=rhs.x; y=rhs.y; return *this;}
  bool operator == (const NodeIndex& rhs) const {return (x==rhs.x && y==rhs.y);}

  // Neighbors
  NodeIndex upleft(void) const {return NodeIndex(x-1, y-1);}
  NodeIndex up(void) const {return NodeIndex(x, y-1);}
  NodeIndex upright(void) const {return NodeIndex(x+1, y-1);}
  NodeIndex left(void) const {return NodeIndex(x-1, y);}
  NodeIndex right(void) const {return NodeIndex(x+1, y);}
  NodeIndex downleft(void) const {return NodeIndex(x-1, y+1);}
  NodeIndex down(void) const {return NodeIndex(x, y+1);}
  NodeIndex downright(void) const {return NodeIndex(x+1, y+1);}
  
  // Returns the distance from this index to the other index
  double distTo(const NodeIndex& to) const
	{
		double dx = to.x-x;
		double dy = to.y-y;
		return sqrt(dx*dx + dy*dy);
	}
	
	union
	{
    struct {int x; int y;};
    struct {int col; int row;};
  };
};

static std::ostream& operator << (std::ostream& os, const NodeIndex& index)
{
  os << "(" << index.x << ", " << index.y << ")";
  return os;
}

// Path is an ordered list of NodeIndices
typedef std::vector<NodeIndex> Path;

#endif // _ASTAR_TYPES_H_
